package gdou.gym.socket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import gdou.gym.entity.SiteApplication;
import gdou.gym.exception.StateCode;
import gdou.gym.exception.SysException;
import gdou.gym.service.space.SpaceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * @Description: 200 表示成功收到客户端的ws请求，(如用户发送的请求和管理员请求)
 * 201 表示服务器发给管理员的请求
 * 202 表示服务器发给用户的请求
 *
 **/

@Controller
@ServerEndpoint(value = "/user/{act}")
@Slf4j
public class UserSocketServer   {
    private static final Object V = new Object();
    private static final ConcurrentHashMap<String, Object> SESSION = new ConcurrentHashMap<>();
    private static SpaceService spaceService;
    private static final ThreadLocal<ObjectMapper> local = ThreadLocal.withInitial(ObjectMapper::new);

    private static final ConcurrentHashMap<String, UserSocketServer> map = new ConcurrentHashMap<>();
    //每个连接都会有自己的会话
    private Session session;
    private String account;

    public static void response(SiteApplication value) throws IOException {
        SocketResponseEntry.SocketResponse response = SocketResponseEntry.SocketResponse.ADMIN_RESPONSE;
        map.get(value.getApplicant()).send(new SocketResponseEntry(value, response));
    }

    @OnOpen
    public void open(@PathParam("act") String account, Session session) throws IOException {
        log.info("用户:{}登陆了", account);
        this.session = session;
        this.account = account;
        map.put(account, this);
    }

    @OnMessage
    public void onMessage(String msg) throws IOException {
        ObjectMapper mapper = local.get();
        try {
            SiteApplication value = mapper.readValue(msg, SiteApplication.class);
            value.setTimestamp(new Date());
            value.setApplicant(account);
            value.setStatus(0);
            AdminSocketServer.request(spaceService.ask4Space(value));
            send(SocketResponseEntry.USER_REQUEST_SUCCESS);
        } catch (JsonProcessingException | SysException e) {
            //  e.printStackTrace();
            send(SocketResponseEntry.USER_REQUEST_FAIL);
        }
    }

    private void send(SocketResponseEntry response) throws IOException {
        send(local.get().writeValueAsString(response));
    }


    @OnClose
    public void close() {
        map.remove(account);
        log.info("{}断开了服务器连接", account);

    }

    @OnError
    public void error(Throwable error) {
        log.error("{}出现了异常", account);
        log.error(error.getMessage());
        map.remove(account);
    }


    private void send(String data) throws IOException {
        if (session.isOpen()) {
            session.getBasicRemote().sendText(data);
        }
    }


    @Autowired
    public void setSpaceService(SpaceService x) {
        spaceService = x;
    }


    public static void addToken(String token) {
        if (SESSION.containsKey(token)) throw new SysException(StateCode.LOGIN_ERROR);
        SESSION.put(token, V);
    }


    private static void removeToken(String token) {
        SESSION.remove(token);
    }
}
